/*`
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */

#include "e_mod_main.h"
#include "e_mod_config.h"

# define D(x)  do {printf(__FILE__ ":%d:  ", __LINE__); printf x; fflush(stdout);} while (0)

/***************************************************************************/
/**/
static void		_eloquence_new				();
static void		_button_cb_mouse_down			(void *data, Evas *e, Evas_Object *obj, void *event_info);

static Eloquence_Face	*_eloquence_face_new			();
static void		_eloquence_face_free			(Eloquence_Face *face);
static void		_eloquence_face_enable			(Eloquence_Face *face);
static void		_eloquence_face_disable			(Eloquence_Face *face);
static void		_eloquence_face_menu_new		(Eloquence_Face *face);

static void		_eloquence_face_cb_menu_configure	(void *data,E_Menu *m, E_Menu_Item *mi);

static void		_eloquence_face_cb_mouse_down		(Eloquence_Face *face,Evas *e, Evas_Object *obj, void *event_info);


static void		_eloquence_face_cb_pre_menu_control	(void *data, E_Menu *menu);
static void		_eloquence_face_cb_post_menu_control	(void *data, E_Menu *menu);
static void		_control_menu_load			(E_Menu *menu, Eloquence_Face *face);

static int		_eloquence_face_switch_theme		(Eloquence_Face *face, const char *theme);
static void		_eloquence_face_switch_player		(Eloquence_Face *face);

static void		callback_player_play_pause		(void *data, Evas_Object *obj, 
      const char *emission, const char *source);
static void		callback_player_track_next		(void *data, Evas_Object *obj, 
      const char *emission, const char *source);
static void		callback_player_track_prev		(void *data, Evas_Object *obj, 
      const char *emission, const char *source);
static void		callback_player_vol_inc			(void *data, Evas_Object *obj, 
      const char *emission, const char *source);
static void		callback_player_vol_dec			(void *data, Evas_Object *obj, 
      const char *emission, const char *source);
static void		callback_player_shuffle			(void *data, Evas_Object *obj, 
      const char *emission, const char *source);
static void		callback_gui_menu			(void *data, Evas_Object *obj, 
      const char *emission, const char *source);

static void		_menu_cb_post				(void *data, E_Menu *m);


/* gadcon requirements */
static E_Gadcon_Client	*_gc_init	(E_Gadcon *gc, const char *name, const char *id,const char *style);
static void		_gc_shutdown	(E_Gadcon_Client *gcc);
static void		 _gc_orient	(E_Gadcon_Client *gcc);
static char		*_gc_label	(void);
static Evas_Object	*_gc_icon	(Evas *evas);

static Eloquence *eloquence = NULL;


/* and actually define the gadcon class that this module provides (just one) */
static const E_Gadcon_Client_Class _gadcon_class = {  
     GADCON_CLIENT_CLASS_VERSION,
     "Eloquence",
     {
	_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon
     }
};

static E_Gadcon_Client *
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) {
     Evas_Object *o;
     E_Gadcon_Client *gcc;
     Instance *inst;
     Eloquence_Face *face;

     inst = E_NEW(Instance, 1);

     eloquence->face->evas = gc->evas;
     _eloquence_face_switch_theme(eloquence->face, eloquence->face->conf->theme);
     _eloquence_face_switch_player(eloquence->face);

     gcc = e_gadcon_client_new(gc, name, id, style, eloquence->face->eloquence_object);

     gcc->data = inst;

     inst->gcc = gcc;
     inst->o_eloquence = eloquence->face->eloquence_object;
     /*inst->main_menu = eloquence->config_menu;
     e_gadcon_client_util_menu_attach(gcc);*/
     evas_object_event_callback_add(inst->o_eloquence, EVAS_CALLBACK_MOUSE_DOWN,
	   _button_cb_mouse_down, inst);

     eloquence->face->inst = inst;
     return gcc;
}

static void
_gc_shutdown(E_Gadcon_Client *gcc) { 
     Instance *inst;

     inst = gcc->data;
     if (inst->main_menu) {
	  e_menu_post_deactivate_callback_set(inst->main_menu, NULL, NULL);
	  e_object_del(E_OBJECT(inst->main_menu));
	  inst->main_menu = NULL;
     }
     evas_object_del(inst->o_eloquence);
     free(inst);
}

static void
_gc_orient(E_Gadcon_Client *gcc) {
     Instance *inst;

     inst = gcc->data;
     e_gadcon_client_min_size_set(gcc, 256, 16);
     e_gadcon_client_aspect_set(gcc, 16, 16);
}

static char *
_gc_label(void) {
     return _("Eloquence");
}

static Evas_Object *
_gc_icon(Evas *evas) {
     Evas_Object *o;
     char buf[4096];

     o = edje_object_add(evas);
     snprintf(buf, sizeof(buf), "%s/module.edj",
	   e_module_dir_get(eloquence->module));
     edje_object_file_set(o, buf, "icon");
     return o;
}




/* Module specific private routines */
static int _eloquence_count;

static E_Config_DD *conf_edd;
static E_Config_DD *conf_face_edd;

void _eloquence_face_cb_config_updated(Eloquence_Face *face) {
     D(("!!! config updated1\n"));
     _eloquence_face_switch_theme( face, face->conf->theme);
     D(("!!! config updated2\n"));
     _eloquence_face_switch_player(face);
}




/* module private routines */
   static void 
_eloquence_new()
{
   Evas_List *managers, *l, *l2, *cl;
   E_Menu_Item *mi;

   _eloquence_count = 0;
   eloquence = E_NEW(Eloquence, 1);

   conf_face_edd = E_CONFIG_DD_NEW("Eloquence_Config_Face", Config_Face);
   conf_edd = E_CONFIG_DD_NEW("Eloquence_Config", Config);
#undef T
#undef De
#define T Config_Face
#define De conf_face_edd
   E_CONFIG_VAL(De, T, enabled, UCHAR);
   E_CONFIG_VAL(De, T, allow_overlap, INT);
   E_CONFIG_VAL(De, T, theme, STR);
   E_CONFIG_VAL(De, T, player, INT);
   E_CONFIG_VAL(De, T, poll_time, DOUBLE);
   E_CONFIG_VAL(De, T, input_charset, STR);

#undef T
#undef De
#define T Config
#define De conf_edd
   E_CONFIG_LIST(De, T, faces, conf_face_edd);

   eloquence->conf = e_config_domain_load("module.eloquence", conf_edd);
   if (!eloquence->conf) {
	eloquence->conf = E_NEW(Config, 1);
   }

   cl = eloquence->conf->faces; 

   Eloquence_Face *face;

   face = _eloquence_face_new();
   if (face) {
	face->eloquence = eloquence;
	eloquence->faces = evas_list_append(eloquence->faces, face);
	if (!cl) {

	     face->conf = E_NEW(Config_Face, 1);
	     face->conf->enabled = 1;
	     face->conf->allow_overlap = 0;
	     face->conf->poll_time = 8.0;
	     face->conf->theme = evas_stringshare_add(THEME_DEFAULT);

#ifdef HAVE_BMP_XMMSCTRL_H
	     face->conf->player = PLAYER_XMMS;
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	     face->conf->player = PLAYER_BMP;
#endif
#ifdef HAVE_BMPX_METADATA_H
	     face->conf->player = PLAYER_BMPX;
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	     face->conf->player = PLAYER_AUDACIOUS;
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	     face->conf->player = PLAYER_MPD;
#endif
#ifdef HAVE_AMAROK
	     face->conf->player = PLAYER_AMAROK;
#endif

#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	     face->conf->player = PLAYER_XMMS2;
#endif
	     face->conf->input_charset = evas_stringshare_add(CHARSET_DEFAULT);
	     eloquence->conf->faces = evas_list_append(
		   eloquence->conf->faces, face->conf);
	}
	else {
	     face->conf = cl->data;
	     cl = cl->next;
	}
	E_CONFIG_LIMIT(face->conf->poll_time, 0.1, 10.0);
	E_CONFIG_LIMIT(face->conf->allow_overlap, 0, 1);

	/*_eloquence_face_menu_new(face);

	  eloquence->config_menu = face->menu; */

	  eloquence->face = face;

   }
}

static Eloquence_Face * _eloquence_face_new() {
     Eloquence_Face *face;

     face = E_NEW(Eloquence_Face, 1);
     if (!face) return NULL;

     return face;
}

   static void
_eloquence_face_free(Eloquence_Face *face) 
{
   if (face->update_timer)
     ecore_timer_del(face->update_timer);
#ifdef HAVE_AMAROK
   if (face->conf->player == PLAYER_AMAROK)
     amarok_free(face);
#endif
   if (face->eloquence_object)
     evas_object_del(face->eloquence_object);
   if (face->event_object)
     evas_object_del(face->event_object);

   if (face->conf->theme)
     evas_stringshare_del(face->conf->theme);

   free(face->conf);
   face->conf = NULL;
   free(face);
   face = NULL;

   _eloquence_count--;
}

static void
_eloquence_face_enable(Eloquence_Face *face) {
     face->conf->enabled = 1;

     if (face->eloquence_object)
       evas_object_show(face->eloquence_object);
     if (face->event_object)
       evas_object_show(face->event_object);

     e_config_save_queue();
}

static void
_eloquence_face_disable(Eloquence_Face *face) {
     face->conf->enabled = 0;

     if (face->eloquence_object)
       evas_object_hide(face->eloquence_object);
     if (face->event_object)
       evas_object_hide(face->event_object);

     e_config_save_queue();
}

static void
_eloquence_face_menu_new(Eloquence_Face *face) {
     E_Menu *mn, *smn;
     E_Menu_Item *mi;
     mn = e_menu_new();
     face->menu = mn;

     mi = e_menu_item_new(mn);
     e_menu_item_label_set(mi, _("Configuration"));
     e_util_menu_item_edje_icon_set(mi, "enlightenment/configuration");
     e_menu_item_callback_set(mi, _eloquence_face_cb_menu_configure, face);


     smn = e_menu_new();
     e_menu_pre_activate_callback_set(smn, _eloquence_face_cb_pre_menu_control, face);
     e_menu_post_deactivate_callback_set(smn, _eloquence_face_cb_post_menu_control, face);

     face->control_menu = smn;
     mi = e_menu_item_new(mn);
     e_menu_item_label_set(mi, _("Control Player"));
     e_menu_item_submenu_set(mi, face->control_menu);

     mi = e_menu_item_new(mn);
     e_menu_item_separator_set(mi, 1);
}

static void
_eloquence_face_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi) {
     Eloquence_Face *face;

     face = data;
     if (!face) return;
     _config_eloquence_module(NULL, face->eloquence);
}

static void
_eloquence_face_cb_mouse_down(Eloquence_Face *face, Evas *e, Evas_Object *obj, void *event_info) {
     /* We just don't use it here and catch all mouse-clicks with the edje */	
}

void draw_text(Eloquence_Face *face) {
     size_t insize = (strlen(face->song))+1;
     size_t avail = insize+2;

     face->song_utf8 = face->outbuf;
     size_t iconv_errorcode = iconv(face->cd, &face->song, &insize, &face->song_utf8, &avail);
     edje_object_part_text_set(face->eloquence_object, "title", face->outbuf);
}

   static void _eloquence_face_cb_pre_menu_control(void *data, E_Menu *menu) {
	Eloquence_Face *face;

	face = data;
	if (menu->realized || !face)
	  return;
	// generate menu
	_control_menu_load(menu, face);
   }

   static void _eloquence_face_cb_post_menu_control(void *data, E_Menu *menu) {
	Eloquence_Face *face;

	face = data;
	if (menu->parent_item && menu->parent_item->active)
	  return;
	// remove all menuitems
	Evas_List *items;
	for (items = menu->items; items; items = items->next)
	  e_object_del(E_OBJECT(items->data));
	evas_list_free(menu->items);
	menu->items = NULL;
   }

   static void _control_menu_load(E_Menu *menu, Eloquence_Face *face) {
	switch (face->conf->player)
	  {
#ifdef HAVE_XMMS_XMMSCTRL_H
	   case PLAYER_XMMS:
	      xmms_init_menu(menu, face);
	      break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	   case PLAYER_XMMS2:
	      xmms2_init_menu(menu, face);
	      break;
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	   case PLAYER_BMP:
	      bmp_init_menu(menu, face);
	      break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	   case PLAYER_BMPX:
	      bmpx_init_menu(menu, face);
	      break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	   case PLAYER_AUDACIOUS:
	      audacious_init_menu(menu, face);
	      break;	      
#endif
#ifdef HAVE_AMAROK
	   case PLAYER_AMAROK:
	      amarok_init_menu(menu, face);
	      break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	   case PLAYER_MPD:
	      mpd_connect(face);
	      mpd_init_menu(menu, face);
	      break;	      
#endif
	  }
   }




static int
_eloquence_face_switch_theme(Eloquence_Face *face, const char *theme) {
     Evas_Object *o;

     face->cd = iconv_open ("UTF-8", face->conf->input_charset);

     char path[PATH_MAX] = PACKAGE_DATA_DIR"/themes/";
     strcat(strcat(path, theme), ".edj");

     o = edje_object_add(face->evas);

     if ( edje_object_file_set(o, path, "eloquence/main") )
       {
	  if (face->eloquence_object)
	    evas_object_del(face->eloquence_object);

	  // don't free if old and new are the same piece of memory (like on startup)
	  if (face->conf->theme != theme){
	       if (face->conf->theme)
		 evas_stringshare_del(face->conf->theme);
	       face->conf->theme = evas_stringshare_add(theme);
	  }

	  face->eloquence_object = o;

	  edje_object_signal_callback_add(o, "pause", "pause", callback_player_play_pause, face);
	  edje_object_signal_callback_add(o, "next", "next", callback_player_track_next, face);
	  edje_object_signal_callback_add(o, "prev", "prev", callback_player_track_prev, face);
	  edje_object_signal_callback_add(o, "inc_vol", "inc_vol", callback_player_vol_inc, face);
	  edje_object_signal_callback_add(o, "dec_vol", "dec_vol", callback_player_vol_dec, face);
	  edje_object_signal_callback_add(o, "shuffle", "shuffle", callback_player_shuffle, face);
	  edje_object_signal_callback_add(o, "options", "options", callback_gui_menu, face);

	  if (face->conf->enabled){
	       evas_object_show(o);
	  }
	  if (!face->event_object){ // no need to recreate
	       o = evas_object_rectangle_add(face->evas);
	       face->event_object = o;
	       evas_object_layer_set(o, 2);
	       evas_object_repeat_events_set(o, 1);
	       evas_object_color_set(o, 0, 0, 0, 0);

	       if (face->conf->enabled)
		 evas_object_show(o);
	  }

	  int w, h;
	  edje_object_size_min_get(o, &w, &h);

	  e_config_save_queue();
       }
     else{  // unable to open theme, keep current
	  evas_object_del(o);
	  o = NULL;
     }
     return o != NULL;
}




static void
   _eloquence_face_switch_player(Eloquence_Face *face) {
	if(face->update_timer)
	  ecore_timer_del(face->update_timer);

#ifdef HAVE_LIBMPD_LIBMPD_H
	if (face->old_player == PLAYER_MPD)
	  eloquence_mpd_disconnect(face);
#endif
#ifdef HAVE_AMAROK
	if (face->old_player == PLAYER_AMAROK)
	  amarok_free(face);
#endif

	switch (face->conf->player)
	  {
#ifdef HAVE_XMMS_XMMSCTRL_H
	   case PLAYER_XMMS:
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    xmms_update_song, face);
	      break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	   case PLAYER_XMMS2:
	      xmms2_connect(face);
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    xmms2_update_song, face);
	      break;
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	   case PLAYER_BMP:
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    bmp_update_song, face);
	      break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	   case PLAYER_BMPX:
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    bmpx_update_song, face);
	      break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	   case PLAYER_AUDACIOUS:
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    audacious_update_song, face);
	      break;	      
#endif
#ifdef HAVE_AMAROK
	   case PLAYER_AMAROK:
	      amarok_init(face);
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    amarok_update_song, face);
	      break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	   case PLAYER_MPD:
	      eloquence_mpd_connect(face);
	      face->update_timer = ecore_timer_add(
		    face->conf->poll_time, 
		    eloquence_mpd_update_song, face);
	      break;	      
#endif
	  }
   }




static void callback_player_play_pause(void *data, 
      Evas_Object *obj, const char *emission, const char *source){
     Eloquence_Face *face;

     face = data;
     switch (face->conf->player)
       {
#ifdef HAVE_XMMS_XMMSCTRL_H
	case PLAYER_XMMS:
	   xmms_control_play_pause(face);
	   break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	case PLAYER_XMMS2:
	   xmms2_control_play_pause(face);
	   break;              
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	case PLAYER_BMP:
	   bmp_control_play_pause(face);
	   break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	case PLAYER_BMPX:
	   bmpx_control_play_pause(face);
	   break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	case PLAYER_AUDACIOUS:
	   audacious_control_play_pause(face);
	   break;	      
#endif
#ifdef HAVE_AMAROK
	case PLAYER_AMAROK:
	   amarok_control_play_pause(face);
	   break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	case PLAYER_MPD:
	   eloquence_mpd_control_play_pause(face);
	   break;              
#endif
       }

}




static void callback_player_track_next(void *data, 
      Evas_Object *obj, const char *emission, const char *source){
     Eloquence_Face *face;

     face = data;
     switch (face->conf->player)
       {
#ifdef HAVE_XMMS_XMMSCTRL_H
	case PLAYER_XMMS:
	   xmms_control_track_next(face);
	   break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	case PLAYER_XMMS2:
	   xmms2_control_track_next(face);
	   break;              
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	case PLAYER_BMP:
	   bmp_control_track_next(face);
	   break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	case PLAYER_BMPX:
	   bmpx_control_track_next(face);
	   break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	case PLAYER_AUDACIOUS:
	   audacious_control_track_next(face);
	   break;	      
#endif
#ifdef HAVE_AMAROK
	case PLAYER_AMAROK:
	   amarok_control_track_next(face);
	   break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	case PLAYER_MPD:
	   eloquence_mpd_control_track_next(face);
	   break;              
#endif
       }

}




static void callback_player_track_prev(void *data, 
      Evas_Object *obj, const char *emission, const char *source){
     Eloquence_Face *face;

     face = data;
     switch (face->conf->player)
       {
#ifdef HAVE_XMMS_XMMSCTRL_H
	case PLAYER_XMMS:
	   xmms_control_track_prev(face);
	   break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	case PLAYER_XMMS2:
	   xmms2_control_track_prev(face);
	   break;              
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	case PLAYER_BMP:
	   bmp_control_track_prev(face);
	   break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	case PLAYER_BMPX:
	   bmpx_control_track_prev(face);
	   break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	case PLAYER_AUDACIOUS:
	   audacious_control_track_prev(face);
	   break;	      
#endif
#ifdef HAVE_AMAROK
	case PLAYER_AMAROK:
	   amarok_control_track_prev(face);
	   break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	case PLAYER_MPD:
	   eloquence_mpd_control_track_prev(face);
	   break;              
#endif
       }

}




static void callback_player_vol_inc(void *data, 
      Evas_Object *obj, const char *emission, const char *source){
     Eloquence_Face *face;

     face = data;
     switch (face->conf->player)
       {
#ifdef HAVE_XMMS_XMMSCTRL_H
	case PLAYER_XMMS:
	   xmms_control_vol_inc(face);
	   break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	case PLAYER_XMMS2:
	   /* xmms2 doesn't yet support this */
	   break;              
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	case PLAYER_BMP:
	   bmp_control_vol_inc(face);
	   break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	case PLAYER_BMPX:
	   bmpx_control_vol_inc(face);
	   break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	case PLAYER_AUDACIOUS:
	   audacious_control_vol_inc(face);
	   break;	      
#endif
#ifdef HAVE_AMAROK
	case PLAYER_AMAROK:
	   amarok_control_vol_inc(face);
	   break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	case PLAYER_MPD:
	   eloquence_mpd_control_vol_inc(face);
	   break;              
#endif
       }

}




static void callback_player_vol_dec(void *data, 
      Evas_Object *obj, const char *emission, const char *source){

     Eloquence_Face *face;

     face = data;
     switch (face->conf->player)
       {
#ifdef HAVE_XMMS_XMMSCTRL_H
	case PLAYER_XMMS:
	   xmms_control_vol_dec(face);
	   break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	case PLAYER_XMMS2:
	   /* xmms2 doesn't yet support this */
	   break;              
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	case PLAYER_BMP:
	   bmp_control_vol_dec(face);
	   break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	case PLAYER_BMPX:
	   bmpx_control_vol_dec(face);
	   break;	      
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	case PLAYER_AUDACIOUS:
	   audacious_control_vol_dec(face);
	   break;	      
#endif
#ifdef HAVE_AMAROK
	case PLAYER_AMAROK:
	   amarok_control_vol_dec(face);
	   break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	case PLAYER_MPD:
	   eloquence_mpd_control_vol_dec(face);
	   break;              
#endif
       }

}




static void callback_player_shuffle(void *data, 
      Evas_Object *obj, const char *emission, const char *source){
     Eloquence_Face *face;

     face = data;
     switch (face->conf->player)
       {
#ifdef HAVE_XMMS_XMMSCTRL_H
	case PLAYER_XMMS:
	   xmms_control_shuffle(face);
	   break;	      
#endif
#ifdef HAVE_BMP_BEEPCTRL_H
	case PLAYER_BMP:
	   /*  disabled because crashing bmp, bad bug in bmp!!!
	       bmp_control_shuffle(face);
	       */
	   break;	      
#endif
#ifdef HAVE_BMPX_METADATA_H
	case PLAYER_BMPX:
	   bmpx_control_shuffle(face);
	   break;	      
#endif
#ifdef HAVE_XMMSCLIENT_XMMSCLIENT_H
	case PLAYER_XMMS2:
	   xmms2_control_shuffle(face);
	   break;
#endif
#ifdef HAVE_AUDACIOUS_BEEPCTRL_H
	case PLAYER_AUDACIOUS:
	   /*  disabled because crashing Audacious, bad bug in Audacious!!!
	       audacious_control_shuffle(face);
	       */
	   break;	      
#endif
#ifdef HAVE_AMAROK
	case PLAYER_AMAROK:
	   amarok_control_shuffle(face);
	   break;	      
#endif
#ifdef HAVE_LIBMPD_LIBMPD_H
	case PLAYER_MPD:
	   eloquence_mpd_control_shuffle(face);
	   break;              
#endif
       }

}




static void
_button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info) {
     Instance *inst;
     Evas_Event_Mouse_Down *ev;

     inst = data;
     ev = event_info;
     if ((ev->button == 1)) {
	  int cx, cy, cw, ch;
	  e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon,
		&cx, &cy, &cw, &ch);
	  e_menu_activate_mouse(inst->main_menu,
		e_util_zone_current_get(e_manager_current_get()),
		cx + ev->output.x, cy + ev->output.y, 1, 1,
		E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
	  evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
		EVAS_BUTTON_NONE, ev->timestamp, NULL);
     }
}
static void
_menu_cb_post(void *data, E_Menu *m) {
}

static void callback_gui_menu(void *data, Evas_Object *obj, 
      const char *emission, const char *source) {
     Eloquence_Face *face;

     face = data;
     Evas_Event_Mouse_Down *ev;
     int cx, cy, cw, ch;
     e_gadcon_canvas_zone_geometry_get(face->inst->gcc->gadcon,
	   &cx, &cy, &cw, &ch);
     e_menu_activate_mouse(face->menu,
	   e_util_zone_current_get(e_manager_current_get()),
	   cx + ev->output.x, cy + ev->output.y, 1, 1,
	   E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
     evas_event_feed_mouse_up(face->inst->gcc->gadcon->evas, ev->button,
	   EVAS_BUTTON_NONE, ev->timestamp, NULL);

}



/* module setup */
EAPI E_Module_Api e_modapi = {
     E_MODULE_API_VERSION,
     "Eloquence"
};

EAPI void *
e_modapi_init(E_Module *m) {

     _eloquence_new();
     eloquence->module = m;

     e_gadcon_provider_register(&_gadcon_class);

     return m;
}

EAPI int
e_modapi_shutdown(E_Module *m) {
     Evas_List *list;

     eloquence->module = NULL;
     e_gadcon_provider_unregister(&_gadcon_class);

     if(eloquence->config_dialog)
       e_object_del(E_OBJECT(eloquence->config_dialog));

     if (eloquence->config_menu)
       {
	  e_menu_post_deactivate_callback_set (eloquence->config_menu, NULL, NULL);
	  e_object_del (E_OBJECT (eloquence->config_menu));
	  eloquence->config_menu = NULL;
       }

     while (eloquence->faces)
       {
	  Eloquence_Face *face;

	  face = eloquence->faces->data;
	  eloquence->faces = evas_list_remove_list (eloquence->faces, eloquence->faces);
	  _eloquence_face_free(face);
       }

     free(eloquence->conf);
     eloquence->conf = NULL;
     free(eloquence);
     eloquence = NULL;
     E_CONFIG_DD_FREE(conf_face_edd);
     E_CONFIG_DD_FREE(conf_edd);

     return 1;
}

EAPI int
e_modapi_save(E_Module *m){
     return 1;
}

EAPI int
e_modapi_about(E_Module *m) {
     e_module_dialog_show(m,_("Eloquence"),
	   _("Music Player Remote Control"));
     return 1;
}


